package com.xhs.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xhs.constant.Constants;
import com.xhs.entity.SysUserEntity;
import com.xhs.response.DownloadUserMergeResponse;
import com.xhs.response.DownloadUserResponse;
import com.xhs.service.DownloadService;
import com.xhs.service.SysUserService;
import com.xhs.utils.ExcelMergeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @desc:
 * @projectName: tools-parent
 * @author: xhs
 * @date: 2023/2/8 13:24
 * @version: JDK 1.8
 */
@Slf4j
@Service
public class DownloadServiceImpl implements DownloadService {

    @Resource
    private SysUserService userService;

    /**
     * 设置表头样式
     *
     * @return WriteCellStyle
     */
    private WriteCellStyle setCellHeadStyle() {
        // 设置样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 创建单元格样式对象
        WriteCellStyle cellStyle = new WriteCellStyle();
        // 下边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        // 左边框
        cellStyle.setBorderLeft(BorderStyle.THIN);
        // 上边框
        cellStyle.setBorderTop(BorderStyle.THIN);
        // 右边框
        cellStyle.setBorderRight(BorderStyle.THIN);

        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 20);
        headWriteCellStyle.setWriteFont(headWriteFont);
        return cellStyle;
    }

    /**
     * 设置数据样式
     *
     * @return WriteCellStyle
     */
    private WriteCellStyle setCellStyle() {
        // 设置样式
        // 创建单元格样式对象
        WriteCellStyle cellStyle = new WriteCellStyle();
        // 纵向居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 下边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        // 左边框
        cellStyle.setBorderLeft(BorderStyle.THIN);
        // 上边框
        cellStyle.setBorderTop(BorderStyle.THIN);
        // 右边框
        cellStyle.setBorderRight(BorderStyle.THIN);
        // 设置自动换行
        cellStyle.setWrapped(true);
        return cellStyle;
    }

    /**
     * 用户信息表导出
     *  @param response response
     */
    @Override
    public void user(HttpServletResponse response) {
        List<SysUserEntity> sysUserList = getSysUserList();
        if (CollectionUtils.isEmpty(sysUserList)) {
            return;
        }
        // 把 List<SysUserEntity> 转为 List<DownloadUserResponse>
        List<DownloadUserResponse> userResponses = sysUserList.stream().map(user -> {
            DownloadUserResponse userRes = new DownloadUserResponse();
            BeanUtils.copyProperties(user, userRes);
            return userRes;
        }).collect(Collectors.toList());
        log.info("----------------导出Excel----------------");
        try {
            // 文件名
            String fileName = "用户信息表" + System.currentTimeMillis() + ExcelTypeEnum.XLSX.getValue();
            String excelName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + excelName);
            // 样式
            HorizontalCellStyleStrategy strategy = new HorizontalCellStyleStrategy(setCellHeadStyle(), setCellStyle());
            // 这里 需要指定写用哪个class去写，然后写到第一个sheet,然后文件流会自动关闭
            EasyExcel.write(response.getOutputStream(), DownloadUserResponse.class)
                    .registerWriteHandler(strategy)
                    .sheet("用户信息")
                    .doWrite(userResponses);
        } catch (Exception e) {
            log.error("用户信息导出异常:{}", e.getMessage());
        }
    }

    /**
     * 用户信息表导出-合并单元格
     *
     * @param response response
     */
    @Override
    public void userMerge(HttpServletResponse response) {
        LambdaQueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<SysUserEntity>().lambda()
                .eq(SysUserEntity::getDelFlg, Constants.DEL_FLG)
                .orderByAsc(SysUserEntity::getPosition);
        List<SysUserEntity> sysUserList = userService.getBaseMapper().selectList(queryWrapper);
        if (CollectionUtils.isEmpty(sysUserList)) {
            return;
        }
        // 把 List<SysUserEntity> 转为 List<DownloadUserResponse>
        List<DownloadUserMergeResponse> userList = sysUserList.stream().map(user -> {
            DownloadUserMergeResponse userRes = new DownloadUserMergeResponse();
            BeanUtils.copyProperties(user, userRes);
            return userRes;
        }).collect(Collectors.toList());
        log.info("----------------导出Excel----------------");
        try {
            //需要合并的列
            int[] mergeColumeIndex = {0};
            // 从那一行开始合并
            int mergeRowIndex = 1;
            // 文件名称
            String fileName = "用户表";
            // sheet名称
            String sheetName = "根据职务合并单元格";
            // 这里URLEncoder.encode可以防止中文乱码
            fileName = URLEncoder.encode(fileName + System.currentTimeMillis(), "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ExcelTypeEnum.XLSX.getValue());
            // 样式
            HorizontalCellStyleStrategy strategy = new HorizontalCellStyleStrategy(setCellHeadStyle(), setCellStyle());
            // 先执行合并策略 合并的数据要相邻，最好查询的数据根据合并的列排序
            ExcelMergeUtil mergeUtil = new ExcelMergeUtil(mergeRowIndex, mergeColumeIndex);
            // 进行写入操作
            EasyExcel.write(response.getOutputStream(), DownloadUserMergeResponse.class)
                    .registerWriteHandler(mergeUtil)
                    .registerWriteHandler(strategy)
                    .sheet(sheetName)
                    .doWrite(userList);
            log.info("----------------导出成功----------------");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户信息导出异常，{}", e.getMessage());
        }
    }

    /**
     * 获取用户信息
     *
     * @return List<SysUserEntity>
     */
    private List<SysUserEntity> getSysUserList() {
        LambdaQueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<SysUserEntity>().lambda()
                .eq(SysUserEntity::getDelFlg, Constants.DEL_FLG);
        return userService.getBaseMapper().selectList(queryWrapper);
    }
}
